package com.zx.flow.api.util;

import cn.hutool.core.io.FileUtil;
import cn.hutool.crypto.digest.MD5;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;

@Slf4j
public class Util {

    private static final ObjectMapper mapper = new ObjectMapper();

    public static String readJosn(String name) throws Exception {
        File file = ResourceUtils.getFile("classpath:bpm/" + name + ".json");
        return FileUtil.readString(file, "utf-8");
    }

    public static List<String> readAllBpmFilenames() throws Exception {
        try {
            File bpmDir = ResourceUtils.getFile("classpath:bpm/");
            if (bpmDir.isDirectory()) {
                File[] files = bpmDir.listFiles((dir, name) -> name.endsWith(".json"));
                List<String> fileNames = Arrays.stream(files).map(file -> file.getName()).collect(Collectors.toList());
                return fileNames;
            }
        } catch (FileNotFoundException e) {
            log.warn("本地流程配置文件不存在，无法加载:{}", e.getMessage());
        }
        return Collections.emptyList();
    }

    public static <T> List<T> findData(List<T> data, T find) {
        if (CollectionUtils.isEmpty(data)) {
            return Collections.emptyList();
        }
        return data.stream().filter(d -> Objects.equals(d, find)).collect(Collectors.toList());
    }

    public static <T> boolean findHas(List<T> data, T find) {
        if (CollectionUtils.isEmpty(data)) {
            return false;
        }
        return data.stream().filter(d -> Objects.equals(d, find)).findAny().isPresent();
    }

    /**
     * 生成对象的唯一id
     *
     * @param obj
     * @return
     */
    public static String uniqueId(Object obj) {
        String jsonString = Util.getJsonStr(obj);
        String id = MD5.create().digestHex(jsonString);
        return id;
    }

    /**
     * 格式化json文本格式
     *
     * @param obj
     * @return
     */
    public static String getJsonStr(Object obj) {
        return JSON.toJSONString(obj,
                JSONWriter.Feature.PrettyFormat, // 格式化样式
                JSONWriter.Feature.WriteMapNullValue,//属性为null的时候就写null,否则字段就没有了
                JSONWriter.Feature.ReferenceDetection //防止循环引用
                //JSONWriter.Feature.WriteEnumUsingToString//处理枚举时调用toString方法。无法正常转换回枚举了
        );
    }

    public static <T> T getJavaObject(String json, Class<T> clazz) {
        return JSONObject.parseObject(json, clazz, JSONReader.Feature.IgnoreSetNullValue);
    }

    public static JSONObject getJsonObject(String json) {
        if (StringUtils.isEmpty(json)) {
            return new JSONObject();
        }
        return JSON.parseObject(json, JSONReader.Feature.IgnoreSetNullValue);
    }

    public static JSONArray getJsonArray(String json) {
        if (StringUtils.isEmpty(json)) {
            return new JSONArray();
        }
        return JSON.parseArray(json, JSONReader.Feature.IgnoreSetNullValue);
    }

    public static String getJsonStr2(Object obj) {
        try {
            return mapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static <T> T getJavaObject2(String jsonStr, Class<T> objClass) {
        try {
            return mapper.readValue(jsonStr, objClass);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }


    public static List<? extends Annotation> getAnnotationInstanceFormSpring(
            Class<? extends Annotation> findAnnotation)
            throws ClassNotFoundException {
        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
        scanner.addIncludeFilter(new AnnotationTypeFilter(findAnnotation));
        Set<BeanDefinition> annotatedClasses = scanner.findCandidateComponents("com.zx");
        List<Annotation> resList = new ArrayList<>();
        for (BeanDefinition beanDefinition : annotatedClasses) {
            String className = beanDefinition.getBeanClassName();
            Class<?> clazz = Class.forName(className);
            Annotation annotation = clazz.getAnnotation(findAnnotation);
            resList.add(annotation);
        }
        return resList;
    }
}
